iT邦幫忙

2023 iThome 鐵人賽

DAY 3
0

平時程式宣告變數或方法參數,套到期望執行的程式邏輯,就能讓寫好的邏輯動起來,但你是否曾想過程式在執行時,背後如何使用定義好的資料,今天第三天配合流程控制來闡述變數的運行機制

開始前先來弄清楚相關名詞定義,程式資料的取得方式分為下列兩種使用方式:

傳值(Pass By Value): 取得參數或變數保存的實際值
傳址(Pass By Refrence): 直接操作目標的記憶體位置

在了解相關名詞後,現在來印證Java是基於傳值方式來操作資料

public static void main(String[] args) {
    int age = 15;
    modifyAge(age);
    System.out.printf("main Method age %d\n", age); 
    // output: I Method modifyAge value is 15
}

static void modifyAge(int a) {
    a = 10;
    System.out.printf("I Method modifyAge value is %d\n", a);
    // output: I Method modifyAge value is 10
}

這段程式碼先在 main方法定義了age 變數並設初始值為15,從打印的結果可以得知外面的age變數,並沒有因為modifyAge方法重新賦值為10,而改變了實際值

現在上第二個範例程式來做比對

static class Son {
    private String name;

    public String getName() {
        return this.name;
    }

    public void setName(String _name) {
        this.name = _name;
    }
}
static void changeName(Son s) {
    s.setName("Bob");
}
public static void main(String[] args) {
    // 建立實例物件
    Son instance = new Son();
    instance.setName("Jeffy");
    System.out.println(instance.getName());
    // output: Jeffy
    changeName(instance);
    System.out.println(instance.getName());
    // output: Bob
}

上述程式碼依序分別打印了 Jeffy和Bob字串,與第一個範例差異在於,外面的局部變數instance屬性name,被changeName方法修改後,也跟著被修改了,在回到開頭的解釋的傳值與傳址的名詞定義,範例一的結果較貼近傳值,第二個範例則是傳址,但其實Java是以傳值方式傳遞參數至方法中

現在修改 changeName的實作邏輯

static void changeName(Son s) {
    s.setName("Bob");

    // 將參數重新賦值到新的 Son實例
    s = new Son();
    s.setName("Lucy");
    System.out.printf("changeName son is %s \n", s.getName());
    // output: changeName son is Lucy
}

實際執行後可以從打印結果發現,外部的變數 instance 屬性並沒影響,反而 changeName的參數 s,就像重新定位了不同參考值,這個行為說明了Java是值參考,原理在於參數s是複製了變數instance的值到方法中

如果是傳址方式使用參數,那麼行為會變成傳遞變數instance的「記憶體位址」到s參數中,此時在 changeName內部將參數 s重新賦值,相當於將對外面的 instance 變數進行操作

參考
菜豬工程師(https://matthung0807.blogspot.com/2019/01/java-pass-by-valuepass-by-reference.html)


上一篇
第二天 讓程式動起來
下一篇
第四天 來看Java怎麼使用記憶體
系列文
掌握Java神器,駕馭SpringBoot猛獸30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言